package Demo_0401;

/**
 * @author:zhengyilong
 * @email:1797344574@qq.com
 * @phone:13479394730
 * @desc:
 * @DateTime:2022/4/1 9:22
 **/
//顺序表存储的数据类型是泛型，所以是泛型类
public class SqListClass<E> {
    final int initcapacity = 10;//线性表的初始容量
    private E[] data;//声明一个数组
    private int size;//线性表的实际长度
    private  int capacity;//最大容量
    public SqListClass(){//构造方法 实例化
        data = (E[]) new Object[initcapacity];
        capacity = initcapacity;
        size = 0;
    }

    //长度等于容量时扩容
    private void updataCapacity(int newCapacity){
        //根据新容量创建新数组    将原来数组的值复制进来
        E[] newdata = (E[]) new Object[newCapacity];
        for (int i = 0;i<size;i++){
            newdata[i] = data[i];
        }
        capacity = newCapacity;//更新容量
        data = newdata;//重新指向
    }

    public void CreateList(E [] e){
        //数组data的下标
        int j = 0;
        for (int i = 0; i < e.length; i++) {
            //考虑data数组装不下的问题    扩容
            if (size == capacity){//装满了
                updataCapacity(capacity*2);
            }
            //将数组e的元素存到数组data里
            data[j] = e[i];
            j++;
            //设置长度size
            size = j;
        }
    }

    //将参数a添加到线性表的末尾。
    public  void Add(E a){
        if (size == capacity){//装满了
            updataCapacity(capacity*2);
        }
        data[size] = a;
        size++;
    }

    //求线性表的长度
    public int size(){
        return size;
    }

    //设置线性表长度为 e
    public void SetSize(int e){
        //考虑e不是正常的长度
        if (e < 0 || e>size){
            throw new IllegalArgumentException("长度不在有效范围内");
        }
        size = e;
    }

    // 返回下标为i 的元素
    public E GetElem(int i){
        if (i<0 || i>size-1){
            throw new IllegalArgumentException("下标i不在合法范围内");
        }
        return (E)data[i];
    }

    //将下标i 的元素赋值为 e
    public void SetElem(int i,E e){
        if (i<0 || i>size-1){
            throw new IllegalArgumentException("下标i不在合法范围内");
        }
        data[i] = e;
    }

    //找出线性表里第一次出现值为 e 的下标
    public int GetNo(E e){
        //遍历数组data，对比e，返回下标
        //for循环 data[i] == e break 数组里面根本没有这个值
        int i = 0;//代表当前遍历到的下标
        while (i<size && !data[i].equals(e)){//循环数组，当有值等于e对的时候，结束循环
            i++;
        }
        if (i >= size){//没有这个值
            return -1;
        }
        return i;
    }

    //将下标 i的元素 和下标 j 的元素进行交换
    public void swap(int i,int j){
        //i 和 j  不是合理下标
        if (i<0 || i>size-1 || j<0 || j>size-1){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        E e = data[i];
        data[i] = data[j];
        data[j] = e;
    }

    //将元素e插入到 i的位置
    public void Insert(int i,E e){
        if (i <0 || i>size){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        for (int j = size;j>i;j--){
            data[j] = data[j-1];
        }
        data[i] = e;
        size++;
    }

    //删除下标为 i 的元素
    public void Delete(int i){
        //判断i是否合理
        if (i <0 || i>size-1){
            throw new IllegalArgumentException("下标不在合法范围内");
        }
        for (int j = i;j<size-1;j++){
            data[j] = data[j+1];//前移了一位
        }
        size--;
        //减容问题 当size = capacity/4 兼容减一半 capacity/2
        if (size == capacity/4 && capacity > initcapacity){
            updataCapacity(capacity/2);
        }
    }

    //将线性表的所有元素拼接成字符串并返回
    public String toString(){
        //遍历数组，元素拼接字符串
        String answer = "";
        for (int i = 0;i<size;i++){
            answer += data[i]+" ";
        }
        return answer;
    }
}

